/*
 *  This file is part of LifeBudget - Copyright 2010 Clifton Eaton
 *  ------------------------------------------------------------------
 *  LifeBudget is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  LifeBudget is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with LifeBudget.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.lifebudget.app.client.mvc.controller;

import org.lifebudget.app.client.events.AppEvents;
import org.lifebudget.app.client.mvc.model.LoginInfo;
import org.lifebudget.app.client.mvc.view.AppView;
import org.lifebudget.app.client.service.LoginService;
import org.lifebudget.app.client.service.LoginServiceAsync;

import com.extjs.gxt.ui.client.event.EventType;
import com.extjs.gxt.ui.client.mvc.AppEvent;
import com.extjs.gxt.ui.client.mvc.Controller;
import com.extjs.gxt.ui.client.mvc.Dispatcher;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.rpc.AsyncCallback;

/**
 * Controller class for the LifeBudget app.  Handles login processing and
 * initialization of the application. Contains a reference to the app's main
 * view.
 */
public class AppController extends Controller {

	/** The user login info. */
	private LoginInfo loginInfo;
	
	/** The overall app view. */
	private AppView appView;

	/**
	 * Instantiates a new app controller, registering all events that <code>AppController</code>
	 * can handle.
	 */
	public AppController() {
		registerEventTypes(AppEvents.Init);
		registerEventTypes(AppEvents.Login);
		registerEventTypes(AppEvents.Error);
	}

	/* (non-Javadoc)
	 * @see com.extjs.gxt.ui.client.mvc.Controller#handleEvent(com.extjs.gxt.ui.client.mvc.AppEvent)
	 */
	public void handleEvent(AppEvent event) {
		EventType type = event.getType();
		if (type == AppEvents.Init) {
			onInit(event);
		} else if (type == AppEvents.Login) {
			onLogin(event);
		} else if (type == AppEvents.Error) {
			onError(event);
		}
	}

	/* (non-Javadoc)
	 * @see com.extjs.gxt.ui.client.mvc.Controller#initialize()
	 */
	public void initialize() {
		appView = new AppView(this);
	}

	/**
	 * Method to hold the logic for handling an error.  Current implementation
	 * only logs the output to the log file.  
	 *
	 * @param ae the <code>AppEvent</code> containing the error event.
	 */
	protected void onError(AppEvent ae) {
		System.out.println("do something better than this");
		System.out.println("error: " + ae.<Object> getData());

	}

	/**
	 * Handles the Init event, forwards the event to the {@link AppletView}.
	 *
	 * @param event the Init event.
	 */
	private void onInit(AppEvent event) {
		// TODO put a reference to each service in the Registry?
		forwardToView(appView, event);

	}

	/**
	 * Handles the Login event by querying the login service and populating the 
	 * {@link LoginInfo} object.
	 *
	 * @param event the Login event.
	 */
	private void onLogin(AppEvent event) {
		LoginServiceAsync loginService = GWT.create(LoginService.class);
		loginService.login(GWT.getHostPageBaseURL(), new AsyncCallback<LoginInfo>() {

			@Override
			public void onSuccess(LoginInfo result) {
				if (result.isLoggedIn()) {
					loginInfo = result;
					// successful login, show app
					Dispatcher.forwardEvent(AppEvents.Init, loginInfo);
				} else {
					loginInfo = result;
					// no one is logged in, show login screen
					forwardToView(appView, AppEvents.Login, loginInfo);
				}

			}

			/* (non-Javadoc)
			 * @see com.google.gwt.user.client.rpc.AsyncCallback#onFailure(java.lang.Throwable)
			 */
			@Override
			public void onFailure(Throwable caught) {
				Dispatcher.forwardEvent(AppEvents.Error, caught);
			}
		});
	}
}
